package com.yangtu.nearbyshop.admin.service;

import com.github.pagehelper.PageInfo;
import com.yangtu.nearbyshop.core.util.ResponseUtil;
import com.yangtu.nearbyshop.db.dao.NearbyshopGoodsProductMapper;
import com.yangtu.nearbyshop.db.domain.*;
import com.yangtu.nearbyshop.db.service.*;
import com.yangtu.nearbyshop.db.vo.ProductVo;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.yangtu.nearbyshop.admin.dao.GoodsAllinone;
import com.yangtu.nearbyshop.admin.util.CatVo;
import com.yangtu.nearbyshop.core.qcode.QCodeService;
import com.yangtu.nearbyshop.db.domain.*;
import com.yangtu.nearbyshop.db.service.*;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.yangtu.nearbyshop.admin.util.AdminResponseCode.*;

@Service
public class AdminGoodsService {
    private final Log logger = LogFactory.getLog(AdminGoodsService.class);

    @Resource
    private NearbyshopGoodsProductMapper nearbyshopGoodsProductMapper;

    @Autowired
    private NearbyshopGoodsService goodsService;
    @Autowired
    private NearbyshopGoodsSpecificationService specificationService;
    @Autowired
    private NearbyshopGoodsAttributeService attributeService;
    @Autowired
    private NearbyshopGoodsProductService productService;
    @Autowired
    private NearbyshopCategoryService categoryService;
    @Autowired
    private NearbyshopBrandService brandService;
    @Autowired
    private NearbyshopCartService cartService;
    @Autowired
    private NearbyshopOrderGoodsService orderGoodsService;
    @Autowired
    private NearbyshopAdminService adminService;

    @Autowired
    private NearbyshopRegionService regionService;

    @Autowired
    private QCodeService qCodeService;

    public Object list(Integer provinceId,Integer cityId,String adminName,String goodsSn, String name,Integer categoryId,
                       Integer page, Integer limit, String sort, String order,String type) {
        Subject currentUser = SecurityUtils.getSubject();
        NearbyshopAdmin admin = (NearbyshopAdmin) currentUser.getPrincipal();
        Integer adminId = admin.getId();
        for( Integer roleId : admin.getRoleIds()){
            if(roleId.equals(new Integer(1))){
                adminId = null;
            }
        }

        if(!StringUtils.isEmpty(adminName)){
            List<NearbyshopAdmin> adminSearch = adminService.findAdmin(adminName);
            if(adminSearch.size()>0){
                admin = adminSearch.get(0);
                adminId = adminSearch.get(0).getId();
            }
        }

        List<Map<String,Object>> goodsDetailList = new ArrayList<>();
        List<NearbyshopGoods> goodsList = goodsService.querySelectiveAdminCity(provinceId,cityId,adminId,goodsSn,
                name, categoryId,page, limit, sort, order,type);
        Map<String, Object> goodsInfo;
        List<NearbyshopAdmin> adminList = adminService.querySelectiveAll(null,1,
                10000,"add_time","asc");
        Map<Integer, NearbyshopAdmin> maps = adminList.stream().collect(Collectors.toMap(NearbyshopAdmin::getId,
                Function.identity(), (key1, key2) -> key2));

        for (NearbyshopGoods nearbyshopGoods: goodsList) {
            goodsInfo = new HashMap<>();
            List<NearbyshopGoodsProduct> products = productService.queryByGid(nearbyshopGoods.getId());
            if(adminId != null){
                nearbyshopGoods.setAdminName(admin.getUsername());
            }else {
                logger.info("nearbyshopGoods=" + nearbyshopGoods);
                logger.info("nearbyshopGoods.getBrandId()=" + nearbyshopGoods.getBrandId());
                logger.info("maps.get(nearbyshopGoods.getBrandId())=" + maps.get(nearbyshopGoods.getBrandId()));
                nearbyshopGoods.setAdminName(maps.get(nearbyshopGoods.getBrandId()).getUsername());
            }

            if(null != nearbyshopGoods.getProvinceId()){
                NearbyshopRegion province = regionService.findById(nearbyshopGoods.getProvinceId());
                if(province != null){
                    nearbyshopGoods.setProvinceName(province.getName());
                }
            }
            if(null != nearbyshopGoods.getCityId()){
                NearbyshopRegion city = regionService.findById(nearbyshopGoods.getCityId());
                if(city != null){
                    nearbyshopGoods.setCityName(city.getName());
                }
            }
            if(null != nearbyshopGoods.getAreaId()){
                NearbyshopRegion area = regionService.findById(nearbyshopGoods.getAreaId());
                if(area != null){
                    nearbyshopGoods.setAreaName(area.getName());
                }
            }

            goodsInfo.put("goodsbrief", nearbyshopGoods);
            goodsInfo.put("productList", products);
            goodsDetailList.add(goodsInfo);
        }

        long total = PageInfo.of(goodsList).getTotal();
        Map<String, Object> data = new HashMap<>();
        data.put("total", total);
        data.put("items", goodsDetailList);

        return ResponseUtil.ok(data);
    }

    private Object validate(GoodsAllinone goodsAllinone) {
        NearbyshopGoods goods = goodsAllinone.getGoods();
        String name = goods.getName();
        if (StringUtils.isEmpty(name)) {
            return ResponseUtil.badArgument("商品名称");
        }
        if(goods.getSortOrder() == null){
            Short od = 10000;
            goods.setSortOrder(od);
        }
        String goodsSn = goods.getGoodsSn();
        if (StringUtils.isEmpty(goodsSn)) {
            NearbyshopGoods lastOne = goodsService.getLastOne();
            Integer gsn = null;
            if(lastOne == null){
                gsn = 2000000;
            }else {
                gsn = Integer.valueOf(lastOne.getGoodsSn());
                if (gsn < 2000000) {
                    gsn = 2000000;
                } else {
                    gsn++;
                }
            }
            goods.setGoodsSn(gsn+"");
//            return ResponseUtil.badArgument();
        }
        // 品牌商可以不设置，如果设置则需要验证品牌商存在

        /*Integer brandId = goods.getBrandId();
        if (brandId != null && brandId != 0) {
            if (brandService.findById(brandId) == null) {
                return ResponseUtil.badArgumentValue();
            }
        }*/
        // 分类可以不设置，如果设置则需要验证分类存在
        Integer categoryId = goods.getCategoryId();
        if (categoryId == null || categoryId < 0) {
           goods.setCategoryId(-1);
        }

        // 如果限制数量未设置或者设置为负数，则代表无限制，默认为-1
        Integer saleLimit = goods.getSaleLimit();
        if (saleLimit == null || saleLimit < 0) {
            goods.setSaleLimit(-1);
        }

        // 下架商品，推送状态和排序都设置为0，不推荐，不排序
        Boolean onSale = goods.getIsOnSale();
        if (!onSale) {
            goods.setPushSort(0);
            goods.setPushStatus(0);
        }

        NearbyshopGoodsAttribute[] attributes = goodsAllinone.getAttributes();
        for (NearbyshopGoodsAttribute attribute : attributes) {
            String attr = attribute.getAttribute();
            if (StringUtils.isEmpty(attr)) {
                return ResponseUtil.badArgument("属性名不能为空");
            }
            String value = attribute.getValue();
            if (StringUtils.isEmpty(value)) {
                return ResponseUtil.badArgument("属性值不能为空");
            }
        }

        NearbyshopGoodsSpecification[] specifications = goodsAllinone.getSpecifications();
        for (NearbyshopGoodsSpecification specification : specifications) {
            String spec = specification.getSpecification();
            if (StringUtils.isEmpty(spec)) {
                return ResponseUtil.badArgument("型号名");
            }
            String value = specification.getValue();
            if (StringUtils.isEmpty(value)) {
                return ResponseUtil.badArgument("型号值");
            }
        }

        NearbyshopGoodsProduct[] products = goodsAllinone.getProducts();
        Subject currentUser = SecurityUtils.getSubject();
        NearbyshopAdmin admin = (NearbyshopAdmin) currentUser.getPrincipal();
        Integer adminId = admin.getId();
        for( Integer roleId : admin.getRoleIds()){
            if(roleId.equals(new Integer(1))){
                adminId = null;
            }
        }
        for (NearbyshopGoodsProduct product : products) {
            Integer number = product.getNumber();
            if (number == null || number < 0) {
                return ResponseUtil.badArgument("商品数量不能为空");
            }

            BigDecimal costPrice = product.getCostPrice();
            if (costPrice == null) {
                return ResponseUtil.badArgument("商品成本不能为空");
            }

            if(adminId == null){
                BigDecimal price = product.getPrice();
                if (price == null) {
                    return ResponseUtil.badArgument("商品售价不能为空");
                }

                BigDecimal platProfit = product.getPlatProfit();
                if (platProfit == null) {
                    //平台抽成固定为成本价的20%
                    product.setPlatProfit(costPrice.multiply(new BigDecimal("0.2")).setScale(2, BigDecimal.ROUND_DOWN).stripTrailingZeros());
                }

                BigDecimal superProfit = product.getSuperProfit();
                if (superProfit == null) {
                    return ResponseUtil.badArgument("总代提成不能为空");
                }

                BigDecimal mercProfit = product.getSuperProfit();
                if (mercProfit == null) {
                    return ResponseUtil.badArgument("团长提成不能为空");
                }
            }

            String[] productSpecifications = product.getSpecifications();
            if (productSpecifications.length == 0) {
                return ResponseUtil.badArgument();
            }
        }

        return null;
    }

    /**
     * 编辑商品
     * <p>
     * TODO
     * 目前商品修改的逻辑是
     * 1. 更新nearbyshop_goods表
     * 2. 逻辑删除nearbyshop_goods_specification、nearbyshop_goods_attribute、nearbyshop_goods_product
     * 3. 添加nearbyshop_goods_specification、nearbyshop_goods_attribute、nearbyshop_goods_product
     * <p>
     * 这里商品三个表的数据采用删除再添加的策略是因为
     * 商品编辑页面，支持管理员添加删除商品规格、添加删除商品属性，因此这里仅仅更新是不可能的，
     * 只能删除三个表旧的数据，然后添加新的数据。
     * 但是这里又会引入新的问题，就是存在订单商品货品ID指向了失效的商品货品表。
     * 因此这里会拒绝管理员编辑商品，如果订单或购物车中存在商品。
     * 所以这里可能需要重新设计。
     */
    @Transactional
    public Object update(GoodsAllinone goodsAllinone) {
        Object error = validate(goodsAllinone);
        if (error != null) {
            return error;
        }

        NearbyshopGoods goods = goodsAllinone.getGoods();
        NearbyshopGoodsAttribute[] attributes = goodsAllinone.getAttributes();
        NearbyshopGoodsSpecification[] specifications = goodsAllinone.getSpecifications();
        NearbyshopGoodsProduct[] products = goodsAllinone.getProducts();

        Integer id = goods.getId();
        // 检查是否存在购物车商品或者订单商品
        // 如果存在则拒绝修改商品。
        /*if (orderGoodsService.checkExist(id)) {
            return ResponseUtil.fail(GOODS_UPDATE_NOT_ALLOWED, "商品已经在订单中，不能修改");
        }*/
        if (cartService.checkExist(id)) {
            cartService.deleteCart(id);
//            return ResponseUtil.fail(GOODS_UPDATE_NOT_ALLOWED, "商品已经在购物车中，不能修改");
        }

        if (products.length == 1) {
            if (products[0].getStockNumber() < products[0].getStartsaleNumber()) {
                return ResponseUtil.fail(GOODS_STOCK_NUM_NOT_ALLOWED, "商品库存配置错误");
            }

            if (products[0].getPrice().compareTo(goods.getRetailPrice()) != 0 ) {
                return ResponseUtil.fail(GOODS_PRICE_SET_FAULT, "规格货品价格必须跟商品当前价格一致");
            }
        }

        //将生成的分享图片地址写入数据库
        String url = qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());
        goods.setShareUrl(url);
//        String shareUrl = qCodeService.createGoodAdverImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());
//        goods.setAdverUrl(shareUrl);

        // 商品基本信息表nearbyshop_goods
        if (goodsService.updateById(goods) == 0) {
            throw new RuntimeException("更新数据失败");
        }

        Integer gid = goods.getId();
        specificationService.deleteByGid(gid);
        attributeService.deleteByGid(gid);
        productService.deleteByGid(gid);

        // 商品规格表nearbyshop_goods_specification
        for (NearbyshopGoodsSpecification specification : specifications) {
            specification.setGoodsId(goods.getId());
            specificationService.add(specification);
        }

        // 商品参数表nearbyshop_goods_attribute
        for (NearbyshopGoodsAttribute attribute : attributes) {
            attribute.setGoodsId(goods.getId());
            attributeService.add(attribute);
        }

        // 商品货品表nearbyshop_product
        for (NearbyshopGoodsProduct product : products) {
            product.setGoodsId(goods.getId());
            //真实可销售数=库存数-起始销售数
            product.setNumber(product.getStockNumber()- product.getStartsaleNumber());
            productService.add(product);
        }
        qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());

        return ResponseUtil.ok();
    }

    @Transactional
    public Object delete(NearbyshopGoods goods) {
        Integer id = goods.getId();
        if (id == null) {
            return ResponseUtil.badArgument();
        }

        Integer gid = goods.getId();
        goodsService.deleteById(gid);
        specificationService.deleteByGid(gid);
        attributeService.deleteByGid(gid);
        productService.deleteByGid(gid);

        cartService.deleteCart(gid);
        return ResponseUtil.ok();
    }

    @Transactional
    public Object push(NearbyshopGoods goods) {
        Integer id = goods.getId();
        if (id == null || goods.getPushStatus() == null) {
            return ResponseUtil.badArgument();
        }
        //如果是取消推荐，则推荐排序归0
        if(goods.getPushStatus().equals(0)){
            goods.setPushSort(0);
        }else {
            List<NearbyshopGoods> goodsList =goodsService.queryAllByPush();
            int max = 0;
            for(NearbyshopGoods shopGoods : goodsList){
                if(shopGoods.getPushSort() > max){
                    max = shopGoods.getPushSort();
                }
            }
            max += 1;
            goods.setPushSort(max);
        }
        goodsService.updateById(goods);
        return ResponseUtil.ok();
    }

    @Transactional
    public Object sortUp(NearbyshopGoods goods) {
        Integer id = goods.getId();
        if (id == null) {
            return ResponseUtil.badArgument();
        }
        List<NearbyshopGoods> goodsList =goodsService.queryAllByPush();
        NearbyshopGoods nowGoods = goodsService.findById(id);
        NearbyshopGoods lastGoods = null;
        for(NearbyshopGoods shopGoods : goodsList){
            if(shopGoods.getPushSort() == nowGoods.getPushSort()){
                break;
            }else {
                lastGoods = shopGoods;
            }
        }
        if(lastGoods != null){
            int temp;
            temp = nowGoods.getPushSort();
            nowGoods.setPushSort(lastGoods.getPushSort());
            lastGoods.setPushSort(temp);
        }else {
            return ResponseUtil.fail(SORT_OUT_RANGE, "无法移动");
        }

        goods.setPushSort(nowGoods.getPushSort());
        goodsService.updateById(goods);

        NearbyshopGoods updateGoods = new NearbyshopGoods();
        updateGoods.setId(lastGoods.getId());
        updateGoods.setPushSort(lastGoods.getPushSort());
        goodsService.updateById(updateGoods);
        return ResponseUtil.ok();
    }

    @Transactional
    public Object sortDown(NearbyshopGoods goods) {
        Integer id = goods.getId();
        if (id == null) {
            return ResponseUtil.badArgument();
        }
        List<NearbyshopGoods> goodsList =goodsService.queryAllByPush();
        NearbyshopGoods nowGoods = goodsService.findById(id);
        NearbyshopGoods nextGoods = null;
        for(NearbyshopGoods shopGoods : goodsList){
            if(shopGoods.getPushSort() > nowGoods.getPushSort()){
                nextGoods = shopGoods;
                break;
            }
        }
        if(nextGoods != null){
            int temp;
            temp = nowGoods.getPushSort();
            nowGoods.setPushSort(nextGoods.getPushSort());
            nextGoods.setPushSort(temp);
        }else {
            return ResponseUtil.fail(SORT_OUT_RANGE, "无法移动");
        }

        goods.setPushSort(nowGoods.getPushSort());
        goodsService.updateById(goods);

        NearbyshopGoods updateGoods = new NearbyshopGoods();
        updateGoods.setId(nextGoods.getId());
        updateGoods.setPushSort(nextGoods.getPushSort());
        goodsService.updateById(updateGoods);
        return ResponseUtil.ok();
    }

    @Transactional
    public Object create(GoodsAllinone goodsAllinone) {
        Object error = validate(goodsAllinone);
        if (error != null) {
            return error;
        }

        NearbyshopGoods goods = goodsAllinone.getGoods();
        NearbyshopGoodsAttribute[] attributes = goodsAllinone.getAttributes();
        NearbyshopGoodsSpecification[] specifications = goodsAllinone.getSpecifications();
        NearbyshopGoodsProduct[] products = goodsAllinone.getProducts();

        String name = goods.getName();
        if (goodsService.checkExistByName(name)) {
            return ResponseUtil.fail(GOODS_NAME_EXIST, "商品名已经存在");
        }

        if (products.length == 1) {
            if (products[0].getStockNumber() == null || products[0].getNumber() == null || products[0].getStartsaleNumber() == null) {
                return ResponseUtil.fail(GOODS_STOCK_NUM_NOT_ALLOWED, "商品库存配置错误");
            }

            if (products[0].getStockNumber() < products[0].getStartsaleNumber()) {
                return ResponseUtil.fail(GOODS_STOCK_NUM_NOT_ALLOWED, "商品库存配置错误");
            }

/*            if (products[0].getPrice().compareTo(goods.getRetailPrice()) != 0 ) {
                return ResponseUtil.fail(GOODS_PRICE_SET_FAULT, "规格货品价格必须跟商品当前价格一致");
            }*/
        }

        // 商品基本信息表nearbyshop_goods
        goods.setShareUrl(null);
        //goods.setAdverUrl(null);
        if(null != goodsAllinone.getAdminId()){
            goods.setBrandId(goodsAllinone.getAdminId());
        }else {
            // 新零售这里将品牌商用作不同的商户。
            Subject currentUser = SecurityUtils.getSubject();
            NearbyshopAdmin admin = (NearbyshopAdmin) currentUser.getPrincipal();
            goods.setBrandId(admin.getId());
        }

        goodsService.add(goods);

        //将生成的分享图片地址写入数据库
        String url = qCodeService.createGoodShareImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());

        if (!StringUtils.isEmpty(url)) {
            goods.setShareUrl(url);
            if (goodsService.updateById(goods) == 0) {
                throw new RuntimeException("更新数据失败");
            }
        }

//        String shareUrl = qCodeService.createGoodAdverImage(goods.getId().toString(), goods.getPicUrl(), goods.getName());
//        if (!StringUtils.isEmpty(shareUrl)) {
//            goods.setAdverUrl(shareUrl);
//            if (goodsService.updateById(goods) == 0) {
//                throw new RuntimeException("更新数据失败");
//            }
//        }


        // 商品规格表nearbyshop_goods_specification
        for (NearbyshopGoodsSpecification specification : specifications) {
            specification.setGoodsId(goods.getId());
            specificationService.add(specification);
        }

        // 商品参数表nearbyshop_goods_attribute
        for (NearbyshopGoodsAttribute attribute : attributes) {
            attribute.setGoodsId(goods.getId());
            attributeService.add(attribute);
        }

        // 商品货品表nearbyshop_product
        for (NearbyshopGoodsProduct product : products) {
            product.setGoodsId(goods.getId());
            //真实可销售数=库存数-起始销售数
            product.setNumber(product.getStockNumber()- product.getStartsaleNumber());
            productService.add(product);
        }
        return ResponseUtil.ok();
    }

    public Object list2() {
        // http://element-cn.eleme.io/#/zh-CN/component/cascader
        // 管理员设置“所属分类”
        List<NearbyshopCategory> l1CatList = categoryService.queryL1();
        List<CatVo> categoryList = new ArrayList<>(l1CatList.size());

        for (NearbyshopCategory l1 : l1CatList) {
            CatVo l1CatVo = new CatVo();
            l1CatVo.setValue(l1.getId());
            l1CatVo.setLabel(l1.getName());

            List<NearbyshopCategory> l2CatList = categoryService.queryByPid(l1.getId());
            List<CatVo> children = new ArrayList<>(l2CatList.size());
            for (NearbyshopCategory l2 : l2CatList) {
                CatVo l2CatVo = new CatVo();
                l2CatVo.setValue(l2.getId());
                l2CatVo.setLabel(l2.getName());
                children.add(l2CatVo);
            }
            l1CatVo.setChildren(children);

            categoryList.add(l1CatVo);
        }

        // http://element-cn.eleme.io/#/zh-CN/component/select
        // 管理员设置“所属品牌商”
        List<NearbyshopBrand> list = brandService.all();
        List<Map<String, Object>> brandList = new ArrayList<>(l1CatList.size());
        for (NearbyshopBrand brand : list) {
            Map<String, Object> b = new HashMap<>(2);
            b.put("value", brand.getId());
            b.put("label", brand.getName());
            brandList.add(b);
        }

        Map<String, Object> data = new HashMap<>();
        data.put("categoryList", categoryList);
        data.put("brandList", brandList);
        return ResponseUtil.ok(data);
    }

    public Object detail(Integer id) {
        NearbyshopGoods goods = goodsService.findById(id);
        NearbyshopAdmin admin = adminService.findAdmin(goods.getBrandId());
        List<NearbyshopGoodsProduct> products = productService.queryByGid(id);
        List<NearbyshopGoodsSpecification> specifications = specificationService.queryByGid(id);
        List<NearbyshopGoodsAttribute> attributes = attributeService.queryByGid(id);

        Integer categoryId = goods.getCategoryId();
        NearbyshopCategory category = categoryService.findById(categoryId);
        Integer[] categoryIds = new Integer[]{};
        if (category != null) {
            Integer parentCategoryId = category.getPid();
            categoryIds = new Integer[]{parentCategoryId, categoryId};
        }

        Map<String, Object> data = new HashMap<>();
        data.put("goods", goods);
        data.put("adminName", admin.getUsername());
        data.put("specifications", specifications);
        data.put("products", products);
        data.put("attributes", attributes);
        data.put("categoryIds", categoryIds);

        return ResponseUtil.ok(data);
    }

    public Object updateGoodsNum(Integer id, Integer goodsNum) {
        List<NearbyshopGoodsProduct> products = productService.queryByGid(id);

        NearbyshopGoodsProduct product = products.get(0);
        if (goodsNum <= product.getStockNumber()) {
            return ResponseUtil.fail(GOODS_STOCK_NUM_NOT_ALLOWED, "更新的库存数必须大于原有库存数");
        }
        product.setNumber(goodsNum - (product.getStockNumber()- product.getNumber()));
        product.setStockNumber(goodsNum);
        productService.update(product);
        return ResponseUtil.ok();
    }

    public List<ProductVo> exportExcel(String adminName, String name, String goodsSn, Integer categoryId ) {
        HashMap<String,Object> map = new HashMap<>();
        map.put("adminName",adminName);
        map.put("name",name);
        map.put("goodsSn",goodsSn);
        map.put("categoryId",categoryId);
        return nearbyshopGoodsProductMapper.exportExcel(map);
    }

    public int updateProduct(List<ProductVo> list) {
        for(ProductVo vo:list){
            nearbyshopGoodsProductMapper.updateProduct(vo);
        }
        return list.size();
    }
}
